﻿using System;

namespace 面向对象_索引器
{
    class Program
    {
        static void Main(string[] args)
        {
            var a = new Person(7, true);
            try
            {               
                int index = 6;
                Console.WriteLine($"你要访问的数据为{a[index]}");
            }
            catch(Exception e)
            {
                Console.WriteLine("读取数据失败");
            }
            // 1. 正常范围的索引值
            Console.WriteLine($"Before = {a}");
            a[7] = 100;
            Console.WriteLine($"After = {a}");
            // 2. 超范围的索引值赋值：
            // a 方案：直接拒绝操作，并提示超索引
            // b 方案： 扩容并赋值
            a[7] = 100;
            Console.WriteLine($"After = {a}");
        }
    }
    // 使用索引器来以数组的访问形式读取类类型实例中的数据（为对象建立索引）
    // 索引器的语法： 类型 this [索引] 
    // 索引器关键字套件： this（实例本身）、 get(得到值)、 set（设置值）、 value （被设置的值）
    // 索引器不必根据整数值类型进行索引，由你决定查找机制
    //  索引器可以被重载
    //  索引器可以有多个形参，如访问二维数组时
    class Person
    {
        // card ：卡片
        private int[] cards;//声明一个int数组来存储卡片
        private bool b;
        public int this[int index]
        {
            get
            {
                if (index >= 0 && index < cards.Length)
                {
                    return cards[index];
                }
                else
                {
                    // throw : 抛出，丢出
                    // exception: 异常
                    // thorw exception:抛出一个异常，用于报告操作失败，一般需要 try 否则容易导致程序表现异常
                    throw new Exception("索引无效");
                }
            }
            set
            {
                if (index >= 0 && index < cards.Length)
                {
                    cards[index] = value;
                }
                else if (index >= cards.Length)
                {
                    // need 需要，resize 重新计算尺寸
                    if (b)
                    {
                        //创建一个数组，把旧的索引不够的替换掉
                        int[] temp = new int[index + 1];//将temp里的值变为无上限，省去每次扩容的麻烦
                        //将原数据和新数据进行拷贝
                        for (int i = 0; i < cards.Length; i++)//将循环次数设为旧数据的长度
                        {
                            temp[i] = cards[i];//给新数据一次次循环直到全部拷贝
                        }
                        //将旧数据的地址换成新数据的地址
                        cards = temp;
                    }
                    else
                    {
                        Console.WriteLine($"数据填充失败，你的索引超了 {index} ，数据量为：{cards.Length}");
                    }

                }
                else
                {
                    throw new Exception("索引无效");
                }
            }
                        
        }
        public Person(int index,bool b)//将卡片初始化
        {
            cards = new int[index];
            this.b = b;
            
        }
        public override string ToString()
        {
            // join : 参与，加入，把一个集合的每一项通过一个分隔符组合成一个字符串
            return string.Join(",", cards);// ctrl+shift+space
        }
    }
}
